1 /* Copyright 2007-2013 The MathWorks, Inc. */
2
3 /*
4 * File: xil_rtio_data_stream.c
5 *
6 * SIL/PIL data stream over the rtIOStream
7 * NOTE: the xil_ide_data_stream.c implementation does not use this module
8 *
9 */
10
11 /* include XIL data stream interface to implement */
12 #include "xil_data_stream.h"
13 /* include XIL initialization interface to implement */
14 #include "xil_interface_lib.h"
15 /* include rtIOStream interface to use */
16 #include "rtiostream.h"
17 /* include Target-side rtIOStream utility APIs */
18 #include "rtiostream_utils.h"
19
20 /* define a buffer to be used for concatenating small
21 * data writes into chunks of reasonable size for transmission */
22 #ifndef RTIOSTREAM_TX_BUFFER_BYTE_SIZE
23 #define RTIOSTREAM_TX_BUFFER_BYTE_SIZE 300
24 #endif
25
26 #ifdef HOST_WORD_ADDRESSABLE_TESTING
27 /* rtIOStream will handle data in single byte chunks
28 *
29 * uint8_T can be > 8-bits for certain portable word sizes
30 * cases (e.g. C2000) so use native type instead */
31 typedef unsigned char IOUnit_T;
32 #else
33 /* rtIOStream will handle data in MemUnit_T size chunks */
34 typedef MemUnit_T IOUnit_T;
35 #endif
36
37 #define WRITE_DATA_AVAIL_SIZE (sizeof(uint32_T))
38 #define COMMAND_COMPLETE_SIZE (sizeof(MemUnit_T))
39 #define WRITE_DATA_AVAIL_IDX 0
40 #define COMMAND_COMPLETE_IDX (WRITE_DATA_AVAIL_IDX + WRITE_DATA_AVAIL_SIZE)
41 #define WRITE_DATA_BUFFER_IDX (COMMAND_COMPLETE_IDX + COMMAND_COMPLETE_SIZE)
42 #define RTIOSTREAM_TX_BUFFER_MEMUNIT_SIZE (RTIOSTREAM_TX_BUFFER_BYTE_SIZE / MEM_UNIT_BYTES)
43 /* WRITE_BUFFER_SIZE must be representable in uint32_T */
44 #define WRITE_BUFFER_SIZE (WRITE_DATA_AVAIL_SIZE + COMMAND_COMPLETE_SIZE + RTIOSTREAM_TX_BUFFER_MEMUNIT_SIZE)
45 #define USED_WRITE_BUFFER_SIZE (WRITE_DATA_AVAIL_SIZE + COMMAND_COMPLETE_SIZE + writeDataAvail)
46
47 static IOUnit_T writeBuffer[WRITE_BUFFER_SIZE];
48 static IOUnit_T * writeDataPtr;
49 static uint32_T writeDataAvail;
50 static MemUnit_T * commandComplete = (MemUnit_T *) &writeBuffer[COMMAND_COMPLETE_IDX];
51
52 /* store stream handle returned by rtio data stream */
53 static int streamID;
54
55 /* call rtIOStreamBlockingSend */
56 static XIL_DATA_STREAM_ERROR_CODE xilRtIOStreamSend(const IOUnit_T * srcPtr, uint32_T size) {
57 XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
58 int rtIOStreamErrorStatus;
59
60 /* Blocks until all requested outgoing data is sent */
61 rtIOStreamErrorStatus = rtIOStreamBlockingSend(streamID,
62 (const void *) srcPtr,
63 size);
64
65 if (rtIOStreamErrorStatus == RTIOSTREAM_ERROR) {
66 errorCode = XIL_WRITE_DATA_ERROR;
67 }
68
69 return errorCode;
70 }
71
72 /* reset the write buffer */
73 static void resetWriteBuffer(void) {
74 writeDataAvail = 0;
75 writeDataPtr = &writeBuffer[WRITE_DATA_BUFFER_IDX];
76 /* ready for next command */
77 *commandComplete = 0;
78 }
79
80 /* send pending writes */
81 static XIL_DATA_STREAM_ERROR_CODE sendWriteBuffer(void) {
82 XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
83 #ifdef HOST_WORD_ADDRESSABLE_TESTING
84 /* writeDataAvail is in terms of IOUnit_T (uint8_T) - convert to MemUnit_T's
85 * assume that writeDataAvail divides exactly */
86 uint32_T writeDataAvailMemUnits = writeDataAvail / MEM_UNIT_BYTES;
87 #else
88 uint32_T writeDataAvailMemUnits = writeDataAvail;
89 #endif
90 /* update writeDataAvail in the writeBuffer */
91 memcpy((void *) &writeBuffer[WRITE_DATA_AVAIL_IDX], &writeDataAvailMemUnits, sizeof(writeDataAvailMemUnits));
92 if (xilRtIOStreamSend(&writeBuffer[WRITE_DATA_AVAIL_IDX], USED_WRITE_BUFFER_SIZE) != XIL_DATA_STREAM_SUCCESS) {
93 /* throw flush error */
94 errorCode = XIL_DATA_FLUSH_ERROR;
95 return errorCode;
96 }
97 /* reset */
98 resetWriteBuffer();
99 return errorCode;
100 }
101
102 XIL_INTERFACE_LIB_ERROR_CODE xilInit(const int argc,
103 void *argv[]) {
104 XIL_INTERFACE_LIB_ERROR_CODE errorCode = XIL_INTERFACE_LIB_SUCCESS;
105 resetWriteBuffer();
106 streamID = rtIOStreamOpen(argc, argv);
107 if (streamID == RTIOSTREAM_ERROR) {
108 errorCode = XIL_INTERFACE_LIB_ERROR;
109 }
110 return errorCode;
111 }
112
113 /* This function must be called prior to terminating the application in order to
114 * ensure an orderly shutdown of communications - data will already have been sent */
115 XIL_INTERFACE_LIB_ERROR_CODE xilTerminateComms(void) {
116 int errorStatus;
117 XIL_INTERFACE_LIB_ERROR_CODE errorCode = XIL_INTERFACE_LIB_SUCCESS;
118 errorStatus = rtIOStreamClose(streamID);
119 if (errorStatus == RTIOSTREAM_ERROR) {
120 errorCode = XIL_INTERFACE_LIB_ERROR;
121 }
122 return errorCode;
123 }
124
125
126 XIL_DATA_STREAM_ERROR_CODE xilWriteData(const MemUnit_T * src, uint32_T size) {
127 XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
128 const IOUnit_T * srcPtr = (const IOUnit_T *) src;
129 size_t transferAmount;
130 uint32_T bufferAvail;
131
132 /* block until all data is processed */
133 while (size > 0) {
134 /* send if we have a full message worth of data */
135 if (writeDataAvail == RTIOSTREAM_TX_BUFFER_MEMUNIT_SIZE) {
136 errorCode = sendWriteBuffer();
137 if (errorCode != XIL_DATA_STREAM_SUCCESS) {
138 return errorCode;
139 }
140 }
141 bufferAvail = RTIOSTREAM_TX_BUFFER_MEMUNIT_SIZE - writeDataAvail;
142 transferAmount = (size_t) MIN(bufferAvail, size);
143 /* copy data into write buffer */
144 memcpy((void *) writeDataPtr, srcPtr, transferAmount);
145 size -= (uint32_T) transferAmount;
146 writeDataAvail += (uint32_T) transferAmount;
147 srcPtr += transferAmount;
148 writeDataPtr += transferAmount;
149 }
150 return errorCode;
151 }
152
153 XIL_DATA_STREAM_ERROR_CODE xilReadData(MemUnit_T * dst, uint32_T size) {
154 XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
155 int rtIOStreamErrorStatus;
156
157 /* Blocks until all requested incoming data is received */
158 rtIOStreamErrorStatus = rtIOStreamBlockingRecv(streamID,
159 (void *) dst,
160 size);
161
162 if (rtIOStreamErrorStatus == RTIOSTREAM_ERROR) {
163 errorCode = XIL_READ_DATA_ERROR;
164 }
165
166 return errorCode;
167 }
168
169 XIL_DATA_STREAM_ERROR_CODE xilDataFlush(void) {
170 XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
171 /* final part of command */
172 *commandComplete = 1;
173 /* send the write buffer */
174 errorCode = sendWriteBuffer();
175 return errorCode;
176 }
177
|